package org.dromara.netbar.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.commons.collections4.map.LinkedMap;
import org.apache.commons.compress.utils.Lists;
import org.dromara.common.core.constant.NetbarConstants;
import org.dromara.common.core.domain.R;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.RedisKeyGeneratorUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.json.utils.JsonUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.netbar.domain.NetbarCoupon;
import org.dromara.netbar.domain.NetbarMemberLevel;
import org.dromara.netbar.domain.NetbarSeatMemberRate;
import org.dromara.netbar.domain.vo.NetbarCouponVo;
import org.dromara.netbar.domain.vo.NetbarMemberLevelVo;
import org.dromara.netbar.mapper.NetbarCouponMapper;
import org.dromara.netbar.mapper.NetbarMemberLevelMapper;
import org.dromara.netbar.mapper.NetbarSeatMemberRateMapper;
import org.dromara.netbar.service.INetbarMemberLevelService;
import org.springframework.stereotype.Service;
import org.dromara.netbar.domain.bo.NetbarSeatTypeBo;
import org.dromara.netbar.domain.vo.NetbarSeatTypeVo;
import org.dromara.netbar.domain.NetbarSeatType;
import org.dromara.netbar.mapper.NetbarSeatTypeMapper;
import org.dromara.netbar.service.INetbarSeatTypeService;
import software.amazon.awssdk.services.s3.endpoints.internal.Value;

import java.math.BigDecimal;
import java.time.Duration;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 座位类型管理Service业务层处理
 *
 * @author Lion Li
 * @date 2025-07-08
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class NetbarSeatTypeServiceImpl implements INetbarSeatTypeService {

    private final NetbarSeatTypeMapper baseMapper;
    private final NetbarCouponMapper couponMapper;
    private final NetbarMemberLevelMapper memberLevelMapper;
    private final NetbarSeatMemberRateMapper seatMemberRateMapper;
    private final INetbarMemberLevelService netbarMemberLevelService;

    /**
     * 查询座位类型管理
     *
     * @param seatTypeId 主键
     * @return 座位类型管理
     */
    @Override
    public NetbarSeatTypeVo queryById(Long seatTypeId){
        return baseMapper.selectVoById(seatTypeId);
    }

    /**
     * 分页查询座位类型管理列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 座位类型管理分页列表
     */
    @Override
    public TableDataInfo<NetbarSeatTypeVo> queryPageList(NetbarSeatTypeBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<NetbarSeatType> lqw = buildQueryWrapper(bo);
        Page<NetbarSeatTypeVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    @Override
    public TableDataInfo<JSONObject> queryPageList2(NetbarSeatTypeBo bo, PageQuery pageQuery) {
        long l = System.currentTimeMillis();
        TableDataInfo<NetbarSeatTypeVo> netbarSeatTypeVoTableDataInfo = queryPageList(bo, pageQuery);
        JSONArray objects = JSONUtil.parseArray(netbarSeatTypeVoTableDataInfo.getRows());
        List<JSONObject> list = objects.toList(JSONObject.class);
        TableDataInfo<JSONObject> newTableData = new TableDataInfo<>();
        newTableData.setCode(netbarSeatTypeVoTableDataInfo.getCode());
        newTableData.setMsg(netbarSeatTypeVoTableDataInfo.getMsg());
        newTableData.setTotal(netbarSeatTypeVoTableDataInfo.getTotal());

        List<Map<String, Object>> headValues = this.getHeadValues(LoginHelper.getTenantId());
        System.out.println(System.currentTimeMillis() - l);

        Long seatTypeId;
        List<String> notSetKeys = List.of("座位Id", "座位类型", "座位代号", "基础费率");
        for (JSONObject jsonObject : list) {
            seatTypeId = jsonObject.getLong("seatTypeId");
            Long finalSeatTypeId = seatTypeId;
            Optional<Map<String, Object>> any = headValues.stream().filter(h -> ((Long) h.get("座位Id")).equals(finalSeatTypeId)).findAny();
            if (any.isPresent()) {
                for (String key : any.get().keySet()) {
                    if (notSetKeys.contains(key)) {
                        continue;
                    }
                    jsonObject.set(key, any.get().get(key));
                }
            }
        }

        newTableData.setRows(list);

        return newTableData;
    }

    /**
     * 查询符合条件的座位类型管理列表
     *
     * @param bo 查询条件
     * @return 座位类型管理列表
     */
    @Override
    public List<NetbarSeatTypeVo> queryList(NetbarSeatTypeBo bo) {
        LambdaQueryWrapper<NetbarSeatType> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<NetbarSeatType> buildQueryWrapper(NetbarSeatTypeBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<NetbarSeatType> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(NetbarSeatType::getSeatTypeId);
        lqw.like(StringUtils.isNotBlank(bo.getSeatTypeName()), NetbarSeatType::getSeatTypeName, bo.getSeatTypeName());
        lqw.like(StringUtils.isNotBlank(bo.getSeatCode()), NetbarSeatType::getSeatCode, bo.getSeatCode());
        return lqw;
    }

    /**
     * 新增座位类型管理
     *
     * @param bo 座位类型管理
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(NetbarSeatTypeBo bo) {
        NetbarSeatType add = MapstructUtils.convert(bo, NetbarSeatType.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        return flag;
    }

    /**
     * 修改座位类型管理
     *
     * @param bo 座位类型管理
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(NetbarSeatTypeBo bo) {
        NetbarSeatType update = MapstructUtils.convert(bo, NetbarSeatType.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(NetbarSeatType entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除座位类型管理信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    @Override
    public List<String> getHeadKeys(String tenantId) {
        Map<String, Long> levelNameIdMap = netbarMemberLevelService.getLevelNameIdMap(tenantId);
        return levelNameIdMap.keySet().stream().toList();
    }

    @Override
    public List<Map<String, Object>> getHeadValues(String tenantId) {
        List<NetbarSeatTypeVo> nstList = queryList(new NetbarSeatTypeBo());
        // 获取会员名称和id
        Map<String, Long> levelNameIdMap = netbarMemberLevelService.getLevelNameIdMap(tenantId);
        // 获取费率 seatMemberRateMapper
        List<NetbarSeatMemberRate> netbarSeatMemberRates = seatMemberRateMapper.selectList();
        // 每个座位的费率
        List<NetbarSeatMemberRate> nowSeatTypeRates = null;
        // 结果列表
        List<Map<String,Object>> resultMap = new ArrayList<>();
        Map<String,Object> map = null;
        for (NetbarSeatTypeVo nst : nstList) {
            map = new LinkedMap<>();
            map.put("座位Id", nst.getSeatTypeId());
            map.put("座位类型", nst.getSeatTypeName());
            map.put("座位代号", nst.getSeatCode());
            map.put("基础费率", nst.getBaseRate());
            nowSeatTypeRates = netbarSeatMemberRates.stream().filter(n -> n.getSeatTypeId().equals(nst.getSeatTypeId())).toList();
            for (String key : levelNameIdMap.keySet()) {
                Optional<NetbarSeatMemberRate> first = nowSeatTypeRates.stream().filter(n -> n.getMemberLevelId().equals(levelNameIdMap.get(key))).findFirst();
                map.put(key, first.isPresent() ? first.get().getMemberRate(): 0);
            }
            resultMap.add(map);
        }
        return resultMap;
    }

    @Override
    public R<?> saveOrUpdate(Map<String, Object> bo) {
        String tenantId = LoginHelper.getTenantId();
        Map<String, Long> levelNameIdMap = netbarMemberLevelService.getLevelNameIdMap(tenantId);
        Long seatTypeId = (Long) bo.get("座位Id");
        String seatTypeName = (String) bo.get("座位类型");
        String seatCode = (String) bo.get("座位代号");
        long baseRate = (Long.parseLong((String) bo.get("基础费率")));
        boolean isAdd = false;
        // 先查询名称或编号是否重复
        LambdaQueryWrapper<NetbarSeatType> lmq = new LambdaQueryWrapper<>();
        lmq.eq(NetbarSeatType::getSeatTypeName, seatTypeName);
        lmq.ne(null != seatTypeId,NetbarSeatType::getSeatTypeId, seatTypeId);
        if (baseMapper.selectCount(lmq) > 0) {
            return R.fail("座位类型名称重复");
        }
        lmq.clear();
        lmq.eq(NetbarSeatType::getSeatCode, seatCode);
        lmq.ne(null != seatTypeId,NetbarSeatType::getSeatTypeId, seatTypeId);
        if (baseMapper.selectCount(lmq) > 0) {
            return R.fail("座位编号重复");
        }
        NetbarSeatTypeVo oldSeatType = null;
        if (null == seatTypeId) {
            NetbarSeatType netbarSeatType = new NetbarSeatType();
            netbarSeatType.setSeatTypeName(seatTypeName);
            netbarSeatType.setSeatCode(seatCode);
            netbarSeatType.setBaseRate(baseRate);
            baseMapper.insert(netbarSeatType);
            seatTypeId = netbarSeatType.getSeatTypeId();
            isAdd = true;
        }else{
            oldSeatType = baseMapper.selectVoById(seatTypeId);
            baseMapper.update(new LambdaUpdateWrapper<NetbarSeatType>()
                .eq(NetbarSeatType::getSeatTypeId,seatTypeId)
                .set(NetbarSeatType::getSeatTypeName,seatTypeName)
                .set(NetbarSeatType::getSeatCode, seatCode)
                .set(NetbarSeatType::getBaseRate, baseRate)
            );
        }
        NetbarSeatMemberRate netbarSeatMemberRate = null;
        List<NetbarSeatMemberRate> netbarSeatMemberRates = new ArrayList<>();
        for (String key : bo.keySet()) {
            if (levelNameIdMap.containsKey(key)) {
                Long levelId = levelNameIdMap.get(key);
                netbarSeatMemberRate = new NetbarSeatMemberRate();
                netbarSeatMemberRate.setSeatTypeId(seatTypeId);
                netbarSeatMemberRate.setMemberLevelId(levelId);
                netbarSeatMemberRate.setMemberRate(Long.parseLong((String)bo.get(key)));
                netbarSeatMemberRates.add(netbarSeatMemberRate);
            }
        }
        // 删除旧的会员费率
        seatMemberRateMapper.delete(new LambdaQueryWrapper<NetbarSeatMemberRate>().eq(NetbarSeatMemberRate::getSeatTypeId, seatTypeId));
        boolean b = seatMemberRateMapper.insertBatch(netbarSeatMemberRates);
        // 将当前座位的名称给已有卡券中座位名进行覆盖
        if (null !=oldSeatType && StringUtils.isNotEmpty(oldSeatType.getSeatTypeName())) {
            List<NetbarCouponVo> netbarCouponVoList = couponMapper.selectVoList(new LambdaQueryWrapper<NetbarCoupon>().eq(NetbarCoupon::getValidArea, seatTypeId));
            if (CollectionUtil.isNotEmpty(netbarCouponVoList)) {
                LambdaUpdateWrapper<NetbarCoupon> uwr = new LambdaUpdateWrapper<>();
                for (NetbarCouponVo netbarCouponVo : netbarCouponVoList) {
                    netbarCouponVo.setCouponName(netbarCouponVo.getCouponName().replace(oldSeatType.getSeatTypeName(),seatTypeName));
                    uwr.eq(NetbarCoupon::getCouponId,netbarCouponVo.getCouponId());
                    uwr.set(NetbarCoupon::getCouponName,netbarCouponVo.getCouponName());
                    couponMapper.update(uwr);
                    uwr.clear();
                }
            }
        }
        // 清除缓存
        RedisUtils.deleteObject(RedisKeyGeneratorUtils.getSeatTypesKey(LoginHelper.getTenantId()));
        return b ? R.ok() : R.fail();
    }

    @Override
    public List<NetbarSeatTypeVo> getSeatTypeVos() {
        String seatTypesKey = RedisKeyGeneratorUtils.getSeatTypesKey(LoginHelper.getTenantId());
        List<NetbarSeatTypeVo> netbarSeatTypeVos = RedisUtils.getCacheList(seatTypesKey);
        if (CollectionUtil.isEmpty(netbarSeatTypeVos)) {
            netbarSeatTypeVos = baseMapper.selectVoList(new LambdaQueryWrapper<NetbarSeatType>().select(NetbarSeatType::getSeatTypeId, NetbarSeatType::getSeatTypeName, NetbarSeatType::getSeatCode));
            RedisUtils.setCacheList(seatTypesKey, netbarSeatTypeVos);
            RedisUtils.expire(seatTypesKey, 60 * 30);
        }
        return netbarSeatTypeVos;
    }

    @Override
    public Long getSeatPriceByMemberLevelAndSeatType(Long memberLevelId, Long seatTypeId) {
        List<NetbarSeatMemberRate> netbarSeatMemberRates = seatMemberRateMapper.selectList(new LambdaQueryWrapper<NetbarSeatMemberRate>().eq(NetbarSeatMemberRate::getSeatTypeId, seatTypeId).eq(NetbarSeatMemberRate::getMemberLevelId, memberLevelId));
        if (CollectionUtil.isNotEmpty(netbarSeatMemberRates)) {
            return netbarSeatMemberRates.get(0).getMemberRate();
        }
        return null;
    }
}
